package mpbft

import (
	"blockchain/public/function"
	"bytes"
	"crypto/sha256"
	"encoding/json"
	"fmt"
)

type commit1Message struct {
	sign string
	tradeHash [32]byte
	nodeSeq int
}

func commit1(nodeSeq int){
	var h [32]byte
	var commit1 commit1Message
	tradeOfNode:=TradeSet[nodeSeq]
	data,_:=json.Marshal(tradeOfNode)
	tradeHash:=sha256.Sum256(data)
	hash:=getPrepare2Mes(nodeSeq)
	if hash!=h&&hash==tradeHash{
		getTradeResult(nodeSeq)
		tradeOfNode=TradeSet[nodeSeq]
		data,_:=json.Marshal(tradeOfNode)
		tradeHash=sha256.Sum256(data)
		commit1.tradeHash=tradeHash
		commit1.sign=function.SignHash(tradeHash,nodeSeq)
		commit1.nodeSeq=nodeSeq
		var flagCommitted1=make(chan bool)
		go sendCommit1ToPrimary(nodeSeq,flagCommitted1,&commit1)
		<-flagCommitted1
		//fmt.Println(tradeHash)
	}else {
		fmt.Println("节点%d commit1阶段出错\n",nodeSeq)
	}
}

func sendCommit1ToPrimary(nodeSeq int,flagCommitted1 chan bool,commit1 *commit1Message)  {
	for i:=0;i<K;i++{
		select {
		case chanPriRecCommit1[primarysSeq[i]]<-*commit1:
			FlagCommitted1[nodeSeq][i]<-true
			close(FlagCommitted1[nodeSeq][i])
		default:
			FlagCommitted1[nodeSeq][i]<-false
			close(FlagCommitted1[nodeSeq][i])
		}
	}
	flagCommitted1<-true
	close(flagCommitted1)
}

func getTradeResult(nodeSeq int){
	for i:=0;i<K*TradeSize;i++{
		if TradeSet[nodeSeq][i].Sender!=""{
			TradeSet[nodeSeq][i].Result=TradeSet[nodeSeq][i].Remainder-TradeSet[nodeSeq][i].Send
		}
	}
}

func getPrepare2Mes(nodeSeq int)[32]byte{
	var tradeHash [32]byte
	var prepare2Verified [K]prepare2Message
	count:=0
	for prepare2:=range chanNodeRecPrepare2[nodeSeq]{
		data:= make([][]byte,2)
		data[0],_=json.Marshal(prepare2.prepareSet1)
		data[1],_=json.Marshal(prepare2.tradeHash)
		data1:=bytes.Join(data,[]byte(""))
		res:=function.VerifySign(data1,prepare2.sign,prepare2.priSeq)
		if res{
			prepare2Verified[count]=prepare2
			count++
		}
	}
	result:=true
	if prepare2Verified[0].sign!=""{
		for i:=0;i<1;i++{//由于cpu限制，这里将N/3+1改为常数个1
			prepare1:=prepare2Verified[0].prepareSet1[i]
			//fmt.Println(prepare1)
			res:=function.VerifySignHash(prepare1.tradeHash,prepare1.sign,prepare1.nodeSeq)
			if !res&&prepare2Verified[0].tradeHash==prepare1.tradeHash{
				result=false
				break
			}
		}
	}else {
		result=false
	}
	if result{
		tradeHash=prepare2Verified[0].prepareSet1[0].tradeHash
		for i:=0;i<K;i++{
			if prepare2Verified[i].tradeHash!=tradeHash{
				fmt.Printf("主节点%d是拜占庭节点\n",prepare2Verified[i].priSeq)
			}
		}
	}
	return tradeHash
}
